﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
#if DOT_NET
using StyleMVVM.Data;

#else
using Windows.Foundation.Metadata;

#endif

namespace StyleMVVM.DependencyInjection
{
	/// <summary>
	/// This interface is used to define an export.
	/// </summary>
	public interface IExportConfiguration : IBaseExportConfiguration
	{
		/// <summary>
		/// Defines the priority to export at
		/// </summary>
		/// <param name="priority"></param>
		/// <returns></returns>
		IExportConfiguration WithPriority(int priority);

		/// <summary>
		/// Export as a particular type
		/// </summary>
		/// <param name="exportType"></param>
		/// <returns></returns>
		IExportConfiguration As(Type exportType);

		/// <summary>
		/// Defines which environment this export should be exported in
		/// </summary>
		/// <param name="environment"></param>
		/// <returns></returns>
		IExportConfiguration InEnvironment(ExportEnvironment environment);

		/// <summary>
		/// Export this type as a particular name
		/// </summary>
		/// <param name="name"></param>
		/// <returns></returns>
		IExportConfiguration AsName(string name);

		/// <summary>
		/// Export will be shared between all callers.
		/// </summary>
		/// <returns></returns>
		IExportConfiguration AndShared();

		/// <summary>
		/// Obsolete infavor of AndSingleton
		/// </summary>
		/// <returns></returns>
		[Obsolete("Obsoleted infavor of AndSingleton")]
		IExportConfiguration AndSharedPermenantly();

		/// <summary>
		/// Export will be treated as a singleton for the lifetime of the container
		/// </summary>
		/// <returns></returns>
		IExportConfiguration AndSingleton();

		/// <summary>
		/// Allows you to mark this export to be cached using an absolute expire time after creation
		/// </summary>
		/// <param name="timeSpan"></param>
		/// <returns></returns>
		IExportConfiguration AndCachedWithAbsoluteExpiration(TimeSpan timeSpan);

		/// <summary>
		/// Allows you to mark this export to be cached using a sliding expiration time
		/// </summary>
		/// <param name="timeSpan"></param>
		/// <returns></returns>
		IExportConfiguration AndCachedWithSlidingExpiration(TimeSpan timeSpan);

		/// <summary>
		/// Uses the first constructor found for importing (this recommended only when you have one constructor)
		/// </summary>
		/// <returns></returns>
		IExportConfiguration ImportDefaultConstructor();

		/// <summary>
		/// Allows you to specify an import constructor
		/// </summary>
		/// <param name="constructorInfo">ConstrcutorInfo object to use during construction</param>
		/// <returns></returns>
		IExportConfiguration ImportConstructor(object constructorInfo);

		/// <summary>
		/// Mark this export as a Core export
		/// </summary>
		/// <param name="startOrder"></param>
		/// <returns></returns>
		IExportConfiguration CoreExport(CoreExportStartOrder startOrder);

		/// <summary>
		/// Mark a property for initialization
		/// </summary>
		/// <param name="propertyName"></param>
		/// <returns></returns>
		IExportConfiguration Initialize(string propertyName);

		/// <summary>
		/// Mark a property for initialization with a particular value
		/// </summary>
		/// <param name="propertyName"></param>
		/// <param name="initalizeValue"></param>
		/// <returns></returns>
		IExportConfiguration Initialize(string propertyName, object initalizeValue);

		/// <summary>
		/// Mark a property for import
		/// </summary>
		/// <param name="propertyName">property name to import</param>
		/// <returns></returns>
		IExportConfiguration ImportProperty(string propertyName);

		/// <summary>
		/// Mark a property for import and specify if its required
		/// </summary>
		/// <param name="propertyName"></param>
		/// <param name="isRequired"></param>
		/// <returns></returns>
		IExportConfiguration ImportProperty(string propertyName, bool isRequired);

		/// <summary>
		/// Mark a property for import and provide an IExportActivator to resolve it
		/// </summary>
		/// <param name="propertyName"></param>
		/// <param name="exportActivator">allows you to provide</param>
		/// <param name="isRequired">is the property required</param>
		/// <returns></returns>
		IExportConfiguration ImportProperty(string propertyName, IExportActivator exportActivator, bool isRequired);

		/// <summary>
		/// Mark a property for imort, specify if its required and specify what export name to use
		/// </summary>
		/// <param name="propertyName"></param>
		/// <param name="isRequired"></param>
		/// <param name="exportName"></param>
		/// <returns></returns>
		[DefaultOverload]
		IExportConfiguration ImportProperty(string propertyName, bool isRequired, string exportName);

		/// <summary>
		/// Mark a property for import
		/// </summary>
		/// <param name="methodName">property name to import</param>
		/// <returns></returns>
		IExportConfiguration ImportMethod(string methodName);

		/// <summary>
		/// Mark a property for import and specify if its required
		/// </summary>
		/// <param name="methodName"></param>
		/// <param name="isRequired"></param>
		/// <returns></returns>
		IExportConfiguration ImportMethod(string methodName, bool isRequired);

		/// <summary>
		/// Mark a property for imort, specify if its required and specify what export name to use
		/// </summary>
		/// <param name="propertyName"></param>
		/// <param name="isRequired"></param>
		/// <param name="exportName"></param>
		/// <returns></returns>
		IExportConfiguration ImportMethod(string methodName, bool isRequired, string exportName);

		/// <summary>
		/// Method to call when activation is done
		/// </summary>
		/// <param name="activationMethod"></param>
		/// <returns></returns>
		IExportConfiguration ActivationMethod(string activationMethod);

		/// <summary>
		/// Specify a custom lifecycle container for export.
		/// </summary>
		/// <param name="container"></param>
		/// <returns></returns>
		IExportConfiguration LifeCycleContainer(ILifeCycleContainer container);

		/// <summary>
		/// Adds a condition to the export
		/// </summary>
		/// <param name="conditionDelegate"></param>
		IExportConfiguration When(ExportConditionDelegate conditionDelegate);

		/// <summary>
		/// Adds a condition to the export
		/// </summary>
		/// <param name="conditionDelegate"></param>
		IExportConfiguration Unless(ExportConditionDelegate conditionDelegate);

		/// <summary>
		/// Adds a condition to the export
		/// </summary>
		/// <param name="condition"></param>
		IExportConfiguration AndCondition(IExportCondition condition);

		/// <summary>
		/// Marks all properties on the object for injection
		/// </summary>
		/// <param name="required"></param>
		/// <returns></returns>
		IExportConfiguration AutoWireProperties(bool required);

		/// <summary>
		/// Adds metadata to an export
		/// </summary>
		/// <param name="metadataName"></param>
		/// <param name="metadataValue"></param>
		/// <returns></returns>
		IExportConfiguration WithMetadata(string metadataName, object metadataValue);

		/// <summary>
		/// You can provide a cleanup method to be called 
		/// </summary>
		/// <param name="disposalCleanupDelegate"></param>
		/// <returns></returns>
		IExportConfiguration DisposalCleanupDelegate(BeforeDisposalCleanupDelegate disposalCleanupDelegate);

		/// <summary>
		/// Allows you to add custom activation logic to process before the object is returned.
		/// </summary>
		/// <param name="enrichWithDelegate"></param>
		/// <param name="priority">order in which to apply enrichments</param>
		/// <returns></returns>
		IExportConfiguration EnrichWith(EnrichWithDelegate enrichWithDelegate, int priority);
	}
}